package cn.zhentao.util;

import com.alibaba.dashscope.app.*;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

/**
 * 阿里云百炼AI工具类
 *
 * @author zhentao
 * @since 2024-07-29
 */
@Slf4j
@Component
public class DashScopeAiUtil {

    @Value("${dashscope.api-key:sk-0e7519f33026415d9b58ff4679ead7c4}")
    private String apiKey;

    @Value("${dashscope.app-id:b8e521e1b0ee4a9cad5b00495a701f16}")
    private String appId;

    // 线程池用于异步处理流式输出
    private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);

    /**
     * AI对话响应结果
     */
    public static class AiResponse {
        private String text;
        private String sessionId;
        private boolean success;
        private String errorMessage;

        public AiResponse(String text, String sessionId, boolean success, String errorMessage) {
            this.text = text;
            this.sessionId = sessionId;
            this.success = success;
            this.errorMessage = errorMessage;
        }

        // Getters
        public String getText() { return text; }
        public String getSessionId() { return sessionId; }
        public boolean isSuccess() { return success; }
        public String getErrorMessage() { return errorMessage; }
    }



    /**
     * 带会话的对话调用
     *
     * @param prompt 用户输入的问题
     * @param sessionId 会话ID，如果为null则创建新会话
     * @return AI响应结果
     */
    public AiResponse callWithSession(String prompt, String sessionId) {
        try {
            ApplicationParam param;

            // 根据是否有会话ID来构建参数
            if (sessionId != null && !sessionId.trim().isEmpty()) {
                param = ApplicationParam.builder()
                        .apiKey(apiKey)
                        .appId(appId)
                        .prompt(prompt)
                        .sessionId(sessionId)
                        .build();
            } else {
                param = ApplicationParam.builder()
                        .apiKey(apiKey)
                        .appId(appId)
                        .prompt(prompt)
                        .build();
            }

            Application application = new Application();
            ApplicationResult result = application.call(param);

            log.info("AI会话调用成功，prompt: {}, sessionId: {}, response: {}",
                    prompt, result.getOutput().getSessionId(), result.getOutput().getText());

            return new AiResponse(
                result.getOutput().getText(),
                result.getOutput().getSessionId(),
                true,
                null
            );

        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            log.error("AI会话调用失败: {}", e.getMessage(), e);
            return new AiResponse(
                null,
                sessionId,
                false,
                e.getMessage()
            );
        }
    }



    /**
     * AI图片生成
     *
     * @param prompt 图片描述提示词
     * @param style 图片风格
     * @param size 图片尺寸
     * @return AI响应结果
     */
    public AiResponse generateImage(String prompt, String style, String size) {
        try {
            log.info("开始AI图片生成，提示词: {}, 风格: {}, 尺寸: {}", prompt, style, size);

            // 构建图片生成的详细提示词
            String imagePrompt = buildImageGenerationPrompt(prompt, style, size);

            // 调用AI服务生成图片
            ApplicationParam param = ApplicationParam.builder()
                    .apiKey(apiKey)
                    .appId(appId)
                    .prompt(imagePrompt)
                    .build();

            Application application = new Application();
            ApplicationResult result = application.call(param);

            log.info("AI图片生成调用成功，prompt: {}, response: {}", imagePrompt, result.getOutput().getText());

            return new AiResponse(
                result.getOutput().getText(),
                result.getOutput().getSessionId(),
                true,
                null
            );

        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            log.error("AI图片生成失败: {}", e.getMessage(), e);
            return new AiResponse(
                null,
                null,
                false,
                e.getMessage()
            );
        }
    }

    /**
     * 构建图片生成提示词
     */
    private String buildImageGenerationPrompt(String prompt, String style, String size) {
        StringBuilder fullPrompt = new StringBuilder();

        fullPrompt.append("作为一个专业的AI图片生成助手，请根据以下要求生成图片：\n\n");
        fullPrompt.append("描述：").append(prompt).append("\n");
        fullPrompt.append("风格：").append(getStyleDescription(style)).append("\n");
        fullPrompt.append("尺寸：").append(size).append("\n\n");

        fullPrompt.append("请生成符合要求的高质量图片，并返回图片的URL地址。");
        fullPrompt.append("如果无法直接生成图片，请提供详细的图片描述，包括构图、色彩、光影等细节。");

        return fullPrompt.toString();
    }

    /**
     * 获取风格描述
     */
    private String getStyleDescription(String style) {
        switch (style.toLowerCase()) {
            case "realistic":
                return "写实风格，高清晰度，真实感强，细节丰富";
            case "cartoon":
                return "卡通风格，色彩鲜艳，可爱有趣，线条清晰";
            case "anime":
                return "动漫风格，日式动画风格，精美细腻";
            case "oil_painting":
                return "油画风格，艺术感强，色彩丰富，笔触明显";
            case "watercolor":
                return "水彩画风格，柔和淡雅，艺术感，透明感";
            case "sketch":
                return "素描风格，黑白线条，简洁明了";
            case "digital_art":
                return "数字艺术风格，现代感强，色彩鲜明";
            default:
                return "高质量，美观大方，专业水准";
        }
    }

    /**
     * 流式输出AI对话
     *
     * @param prompt 用户输入的问题
     * @return SseEmitter 用于流式输出
     */
    public SseEmitter streamCall(String prompt) {
        return streamCall(prompt, null);
    }

    /**
     * 带会话的流式输出AI对话
     *
     * @param prompt 用户输入的问题
     * @param sessionId 会话ID，如果为null则创建新会话
     * @return SseEmitter 用于流式输出
     */
    public SseEmitter streamCall(String prompt, String sessionId) {
        SseEmitter emitter = new SseEmitter(120000L); // 120秒超时

        executorService.execute(() -> {
            try {
                // 模拟流式输出，因为DashScope SDK可能不直接支持流式
                // 我们先获取完整响应，然后分块发送
                AiResponse response = callWithSession(prompt, sessionId);

                if (response.isSuccess()) {
                    String fullText = response.getText();
                    String[] words = fullText.split("");

                    // 发送开始事件
                    emitter.send(SseEmitter.event()
                            .name("start")
                            .data("{\"type\":\"start\",\"sessionId\":\"" + response.getSessionId() + "\"}"));

                    // 逐字发送响应
                    for (int i = 0; i < words.length; i++) {
                        String word = words[i];
                        try {
                            emitter.send(SseEmitter.event()
                                    .name("data")
                                    .data("{\"type\":\"data\",\"content\":\"" + word.replace("\"", "\\\"") + "\"}"));

                            // 添加延迟以模拟打字效果
                            Thread.sleep(50);
                        } catch (Exception sendException) {
                            log.warn("发送数据失败，可能客户端已断开连接: {}", sendException.getMessage());
                            return; // 停止发送
                        }
                    }

                    // 发送完成事件
                    emitter.send(SseEmitter.event()
                            .name("end")
                            .data("{\"type\":\"end\",\"sessionId\":\"" + response.getSessionId() + "\"}"));

                } else {
                    // 发送错误事件
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data("{\"type\":\"error\",\"message\":\"" + response.getErrorMessage() + "\"}"));
                }

                emitter.complete();

            } catch (Exception e) {
                log.error("流式输出异常: {}", e.getMessage(), e);
                try {
                    // 尝试发送错误事件，如果失败则忽略（可能emitter已经完成）
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data("{\"type\":\"error\",\"message\":\"" + e.getMessage() + "\"}"));
                } catch (Exception sendException) {
                    log.debug("无法发送错误事件，emitter可能已完成: {}", sendException.getMessage());
                }

                try {
                    emitter.completeWithError(e);
                } catch (Exception completeException) {
                    log.debug("无法完成emitter，可能已完成: {}", completeException.getMessage());
                }
            }
        });

        return emitter;
    }

    /**
     * 更快的流式输出（按词分割）
     *
     * @param prompt 用户输入的问题
     * @param sessionId 会话ID
     * @return SseEmitter 用于流式输出
     */
    public SseEmitter fastStreamCall(String prompt, String sessionId) {
        SseEmitter emitter = new SseEmitter(120000L); // 120秒超时

        executorService.execute(() -> {
            try {
                AiResponse response = callWithSession(prompt, sessionId);

                if (response.isSuccess()) {
                    String fullText = response.getText();
                    String[] chunks = fullText.split("(?<=。)|(?<=！)|(?<=？)|(?<=\\.)");

                    // 发送开始事件
                    emitter.send(SseEmitter.event()
                            .name("start")
                            .data("{\"type\":\"start\",\"sessionId\":\"" + response.getSessionId() + "\"}"));

                    // 按句子发送响应
                    for (String chunk : chunks) {
                        if (!chunk.trim().isEmpty()) {
                            try {
                                emitter.send(SseEmitter.event()
                                        .name("data")
                                        .data("{\"type\":\"data\",\"content\":\"" + chunk.replace("\"", "\\\"") + "\"}"));

                                Thread.sleep(200); // 每句话间隔200ms
                            } catch (Exception sendException) {
                                log.warn("发送数据失败，可能客户端已断开连接: {}", sendException.getMessage());
                                return; // 停止发送
                            }
                        }
                    }

                    // 发送完成事件
                    emitter.send(SseEmitter.event()
                            .name("end")
                            .data("{\"type\":\"end\",\"sessionId\":\"" + response.getSessionId() + "\"}"));

                } else {
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data("{\"type\":\"error\",\"message\":\"" + response.getErrorMessage() + "\"}"));
                }

                emitter.complete();

            } catch (Exception e) {
                log.error("快速流式输出异常: {}", e.getMessage(), e);
                try {
                    // 尝试发送错误事件，如果失败则忽略（可能emitter已经完成）
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data("{\"type\":\"error\",\"message\":\"" + e.getMessage() + "\"}"));
                } catch (Exception sendException) {
                    log.debug("无法发送错误事件，emitter可能已完成: {}", sendException.getMessage());
                }

                try {
                    emitter.completeWithError(e);
                } catch (Exception completeException) {
                    log.debug("无法完成emitter，可能已完成: {}", completeException.getMessage());
                }
            }
        });

        return emitter;
    }

    /**
     * 优化的流式输出（适合小程序使用）
     *
     * @param prompt 用户输入的问题
     * @param sessionId 会话ID
     * @param streamType 流式类型（word/sentence/paragraph）
     * @return SseEmitter 用于流式输出
     */
    public SseEmitter optimizedStreamCall(String prompt, String sessionId, String streamType) {
        SseEmitter emitter = new SseEmitter(180000L); // 180秒超时（3分钟），适合小程序

        executorService.execute(() -> {
            try {
                AiResponse response = callWithSession(prompt, sessionId);

                if (response.isSuccess()) {
                    String fullText = response.getText();

                    // 发送开始事件
                    emitter.send(SseEmitter.event()
                            .name("start")
                            .data("{\"type\":\"start\",\"sessionId\":\"" + response.getSessionId() + "\",\"streamType\":\"" + streamType + "\"}"));

                    // 根据流式类型分割内容
                    String[] chunks = splitTextByType(fullText, streamType);
                    int delay = getDelayByType(streamType);

                    // 逐块发送响应
                    for (int i = 0; i < chunks.length; i++) {
                        String chunk = chunks[i];
                        if (!chunk.trim().isEmpty()) {
                            try {
                                emitter.send(SseEmitter.event()
                                        .name("data")
                                        .data("{\"type\":\"data\",\"content\":\"" + escapeJson(chunk) + "\",\"index\":" + i + ",\"total\":" + chunks.length + "}"));

                                Thread.sleep(delay);
                            } catch (Exception sendException) {
                                log.warn("发送数据块失败，可能客户端已断开连接: {}", sendException.getMessage());
                                return; // 客户端断开连接，直接返回
                            }
                        }
                    }

                    // 发送完成事件
                    try {
                        emitter.send(SseEmitter.event()
                                .name("end")
                                .data("{\"type\":\"end\",\"sessionId\":\"" + response.getSessionId() + "\",\"totalChunks\":" + chunks.length + "}"));
                    } catch (Exception sendException) {
                        log.warn("发送完成事件失败，可能客户端已断开连接: {}", sendException.getMessage());
                        return;
                    }

                } else {
                    // 发送错误事件
                    try {
                        emitter.send(SseEmitter.event()
                                .name("error")
                                .data("{\"type\":\"error\",\"message\":\"" + escapeJson(response.getErrorMessage()) + "\"}"));
                    } catch (Exception sendException) {
                        log.warn("发送错误事件失败，可能客户端已断开连接: {}", sendException.getMessage());
                        return;
                    }
                }

                try {
                    emitter.complete();
                } catch (Exception completeException) {
                    log.warn("完成SSE连接失败: {}", completeException.getMessage());
                }

            } catch (Exception e) {
                log.error("优化流式输出异常: {}", e.getMessage(), e);
                try {
                    // 尝试发送错误事件
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data("{\"type\":\"error\",\"message\":\"" + escapeJson(e.getMessage()) + "\"}"));
                } catch (Exception sendException) {
                    log.debug("无法发送错误事件，emitter可能已完成: {}", sendException.getMessage());
                }

                try {
                    emitter.completeWithError(e);
                } catch (Exception completeException) {
                    log.debug("无法完成emitter，可能已完成: {}", completeException.getMessage());
                }
            }
        });

        return emitter;
    }

    /**
     * 根据类型分割文本
     */
    private String[] splitTextByType(String text, String streamType) {
        switch (streamType.toLowerCase()) {
            case "word":
                return text.split("");
            case "sentence":
                return text.split("(?<=[。！？.!?])");
            case "paragraph":
                return text.split("\\n\\s*\\n");
            default:
                // 默认按句子分割
                return text.split("(?<=[。！？.!?])");
        }
    }

    /**
     * 根据类型获取延迟时间
     */
    private int getDelayByType(String streamType) {
        switch (streamType.toLowerCase()) {
            case "word":
                return 30; // 30ms per word
            case "sentence":
                return 150; // 150ms per sentence
            case "paragraph":
                return 300; // 300ms per paragraph
            default:
                return 100; // 默认100ms
        }
    }

    /**
     * JSON字符串转义
     */
    private String escapeJson(String text) {
        if (text == null) return "";
        return text.replace("\\", "\\\\")
                  .replace("\"", "\\\"")
                  .replace("\n", "\\n")
                  .replace("\r", "\\r")
                  .replace("\t", "\\t");
    }



    /**
     * 图片生成响应结果
     */
    public static class ImageResponse {
        private String imageUrl;
        private String taskId;
        private boolean success;
        private String errorMessage;

        public ImageResponse(String imageUrl, String taskId, boolean success, String errorMessage) {
            this.imageUrl = imageUrl;
            this.taskId = taskId;
            this.success = success;
            this.errorMessage = errorMessage;
        }

        // Getters
        public String getImageUrl() { return imageUrl; }
        public String getTaskId() { return taskId; }
        public boolean isSuccess() { return success; }
        public String getErrorMessage() { return errorMessage; }
    }






}
